package com.example.htmlfx.controller;

import com.example.htmlfx.component.AlertComponent;
import com.example.htmlfx.component.LoadingProgressComponent;
import com.example.htmlfx.entity.ParsingResultEntity;
import com.example.htmlfx.utils.DataSaveUtils;
import com.example.htmlfx.utils.HtmlParsingUtils;
import de.felixroske.jfxsupport.FXMLController;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.Pair;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

/**
 * @author gzkemays
 * @date 2021/8/4
 */
@FXMLController
public class TableController implements Initializable {

  @FXML private Label otherTutorials;
  @FXML private Button clearBtn;
  @FXML private Label htmlTutorials;
  @FXML private Label urlTutorials;
  @FXML private ImageView image;
  @FXML private SplitPane splitPane;
  @FXML private CheckBox checkCells;
  @FXML private TableView<ParsingResultEntity> tableView;
  @FXML private TableColumn<ParsingResultEntity, String> url;
  @FXML private TableColumn<ParsingResultEntity, String> type;
  @FXML private TableColumn<ParsingResultEntity, CheckBox> checkBoxColumn;
  @FXML private TextArea htmlArea;
  @FXML private TextField urlField;
  @FXML public RadioButton switchCss;
  @FXML public RadioButton switchJs;
  @FXML private RadioButton openTread;
  @FXML private RadioButton openCompression;
  @FXML private Button parseBtn;
  @FXML private Button downloadBtn;
  private Stage stage;

  private ResourceBundle resourceBundle;

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    // 设置默认图片
    image.setImage(new Image(String.valueOf(getClass().getResource("/images/yzj_icon3.png"))));
    // 获取横向 split 布局，并监听其横拉事件，不让其发生横拉
    for (SplitPane.Divider divider : splitPane.getDividers()) {
      divider
          .positionProperty()
          .addListener((observable, oldValue, newValue) -> divider.setPosition(0.4270557029177719));
    }
    // 提供默认值作为案例
    ObservableList<ParsingResultEntity> entities =
        FXCollections.observableArrayList(
            new ParsingResultEntity("示例地址", "数据类型示例"),
            new ParsingResultEntity("http://img.yeziji.xyz/yzj-di.png", "图片"),
            new ParsingResultEntity("www.bing.com", "地址"));
    // 设置可编辑
    tableView.setEditable(true);
    // tableview 单元格的点击事件
    tableView.setRowFactory(
        tv -> {
          TableRow<ParsingResultEntity> row = new TableRow<>();
          row.setOnMouseClicked(
              event -> {
                if (event.getClickCount() == 2 && (!row.isEmpty())) {
                  ParsingResultEntity item = row.getItem();
                  try {
                    image.setImage(new Image(item.getUrl(), 319.0, 232.0, true, true));
                  } catch (Exception e) {
                    AlertComponent.exceptionErrorArea(e, "如果确保选中的数据类型是“图片”依然报错，请将以下日志给开发者看看。");
                  }
                }
              });
          return row;
        });
    // 绑定参数值
    url.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().getUrl()));
    type.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().getType()));
    // 绑定为 checkBox
    checkBoxColumn.setCellValueFactory(
        cell -> cell.getValue().getCheckBoxComponent().getCheckBox());
    tableView.setItems(entities);
  }

  /**
   * 解析 url 或者 html
   *
   * @param actionEvent 当前点击事件组件
   */
  public void parsing(ActionEvent actionEvent) {
    LoadingProgressComponent component = new LoadingProgressComponent(stage, "解析中...");
    String urlFieldText = urlField.getText();
    String htmlAreaText = htmlArea.getText();
    ObservableList<ParsingResultEntity> entities = FXCollections.observableArrayList();
    if (!StringUtils.hasLength(urlFieldText.trim()) && !StringUtils.hasLength(htmlAreaText.trim())) {
      AlertComponent.normalErrorTips("请填写 HTML 或 URL 其中一个，也可以都填写。");
      return;
    }
    final boolean[] hasData = {true};
    component.activateProgressBar(
        new Task<Boolean>() {
          @Override
          protected Boolean call() throws Exception {
            HtmlParsingUtils build =
                HtmlParsingUtils.builder()
                    .switchCss(switchCss.isSelected())
                    .openThread(openTread.isSelected())
                    .build();
            if (StringUtils.hasLength(urlFieldText.trim())) {
              List<String> images = build.parsingImages(urlFieldText);
              for (String image : images) {
                entities.add(new ParsingResultEntity(image, "图片"));
              }
            }
            if (StringUtils.hasLength(htmlAreaText.trim())) {
              List<String> images = build.parsingHtml(htmlAreaText);
              for (String image : images) {
                entities.add(new ParsingResultEntity(image, "图片"));
              }
            }
            if (!entities.isEmpty()) {
              tableView.setItems(entities);
              checkCells.setSelected(false);
            } else {
              throw new Exception("查询数据为空");
            }
            return true;
          }
        },
        () -> AlertComponent.normalInformationTips("很遗憾没有解析到图片哦，可以尝试手动去看看或者联系开发者呢。(●'◡'●)"));
  }

  /**
   * 下载选中文件
   *
   * @param actionEvent 下载按钮点击事件
   */
  public void download(ActionEvent actionEvent) {
    // 获取保存的路径
    DirectoryChooser directoryChooser = new DirectoryChooser();
    File file = directoryChooser.showDialog(stage);
    LoadingProgressComponent component = new LoadingProgressComponent(stage, "下载中...");
    component.activateProgressBar(
        new Task<Boolean>() {
          @Override
          protected Boolean call() throws Exception {
            if (file != null) {
              String path = file.getPath();
              if (openCompression.isSelected()) {
                DataSaveUtils.downloadFilesToZip(path, tableView.getItems());
              } else {
                for (ParsingResultEntity item : tableView.getItems()) {
                  if (item.getCheckBoxComponent().selected()) {
                    DataSaveUtils.downloadFiles(path, item.getUrl());
                  }
                }
              }
            }
            return true;
          }
        },
        () -> {});
  }

  /** checkBox 全选 */
  public void checkAll(ActionEvent actionEvent) {
    boolean selected = checkCells.isSelected();
    ObservableList<ParsingResultEntity> items = tableView.getItems();
    if (selected) {
      for (ParsingResultEntity item : items) {
        item.getCheckBoxComponent().getSelected();
      }
    } else {
      for (ParsingResultEntity item : items) {
        item.getCheckBoxComponent().noSelected();
      }
    }
  }

  /**
   * 清空现有数据
   *
   * @param actionEvent 点击清空数据按钮
   */
  public void clearData(ActionEvent actionEvent) {
    ObservableList<ParsingResultEntity> observableList = FXCollections.observableArrayList();
    tableView.setItems(observableList);
    htmlArea.setText("");
    urlField.setText("");
    image.setImage(new Image(String.valueOf(getClass().getResource("/images/yzj_icon3.png"))));
  }

  /**
   * url 解析教程
   *
   * @param mouseEvent url 点击事件
   */
  public void urlTutorials(MouseEvent mouseEvent) throws FileNotFoundException {
    tutorials("http://img.yeziji.xyz/htmlfx/url%E8%A7%A3%E6%9E%90%E6%95%99%E7%A8%8B.gif");
  }

  /**
   * html 解析教程
   *
   * @param mouseEvent html 点击事件
   */
  public void htmlTutorials(MouseEvent mouseEvent) throws FileNotFoundException {
    tutorials("http://img.yeziji.xyz/htmlfx/html%E8%A7%A3%E6%9E%90%E6%95%99%E7%A8%8B.gif");
  }

  public void otherTutorials(MouseEvent mouseEvent) throws FileNotFoundException {
    tutorials(
        "http://img.yeziji.xyz/htmlfx/%E7%95%AA%E5%A4%96%E8%A7%A3%E6%9E%90%E6%95%99%E7%A8%8B.gif");
  }

  /**
   * 教程统一方法
   *
   * @param url 文件地址
   */
  private void tutorials(String url) {
    LoadingProgressComponent loadingProgressComponent =
        new LoadingProgressComponent(stage, "图片有点大耐心等一下╰(￣ω￣ｏ)...");
    Dialog<Pair<String, String>> dialog = new Dialog<>();
    dialog.setTitle("url 解析教程");
    dialog.setHeaderText(null);
    dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CANCEL);
    // 插入画布
    GridPane grid = new GridPane();
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(20, 150, 10, 10));
    // 加入取消按钮
    loadingProgressComponent.activateProgressBar(
        new Task<Boolean>() {
          @Override
          protected Boolean call() throws Exception {
            dialog.getDialogPane().setContent(grid);
            Image img = new Image(url, 1024, 1024, true, true);
            ImageView imgView = new ImageView(img);
            grid.add(imgView, 0, 0);
            dialog.showAndWait();
            return true;
          }
        },
        () -> {
          // 失败也打开
          dialog.getDialogPane().setContent(grid);
          dialog.showAndWait();
        });
  }
}
